package org.budo.graph.view;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.budo.graph.Constant;
import org.budo.graph.view.util.ApplicationForceUtil;
import org.budo.graph.view.util.BudoGraphViewUtil;
import org.budo.graph.view.util.GraphAuthorizeUtil;
import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.servlet.util.ResponseUtil;
import org.budo.support.slf4j.Slf4j;
import org.budo.support.spring.util.SpringUtil;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContext;

import com.alibaba.druid.support.json.JSONUtils;

import lombok.Getter;
import lombok.Setter;

/**
 * @author limingwei
 */
@Getter
@Setter
public abstract class AbstractBudoGraphViewSupport {
    private static final Logger log = Slf4j.getLogger();

    public static final String PARAM_NAME_USERNAME = "loginUsername";

    public static final String PARAM_NAME_PASSWORD = "loginPassword";

    protected static final String USERS_CONFIG_KEY = "users";

    private String userFile = "/budo-graph-user.properties";

    private Map<String, String> userMap = MapUtil.stringMap();

    protected boolean handleBudoGraphRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ApplicationContext applicationContext = SpringUtil.getApplicationContext(request);
        String requestURI = request.getRequestURI();

        log.debug("#52 handleBudoGraphRequest, requestURI={}, this={}", requestURI, this);

        // 不需要session的请求
        if (StringUtil.contains(requestURI, "/budo-metric") || StringUtil.contains(requestURI, "/healthz") //
                || StringUtil.contains(requestURI, "/upstream")) {
            request.getSession().invalidate(); // 清理 session
            BudoGraphViewUtil.writeApiResponse(request, response, applicationContext);
            return true;
        }

        // 静态资源请求
        if (requestURI.endsWith("login.html") //
                || requestURI.endsWith("index.html") //
                || StringUtil.endsWith(requestURI, ".css") //
                || StringUtil.endsWith(requestURI, ".js")) {
            BudoGraphViewUtil.writeStaticResponse(applicationContext, request, response);
            return true;
        }

        // 登录校验请求
        if (requestURI.endsWith("submitLogin")) {
            this.writeSubmitLoginResponse(request, (HttpServletResponse) response);
            return true;
        }

        // 认证检查通过
        Boolean checkSession = GraphAuthorizeUtil.checkSession(this, request);
        if (!checkSession) {
            GraphAuthorizeUtil.handleNoSession(request, response);
            return true;
        }

        // 需要session的请求 业务接口
        return this.handleRequest(request, response, requestURI, applicationContext);
    }

    private Boolean handleRequest(HttpServletRequest request, HttpServletResponse response, String requestURI, ApplicationContext applicationContext) throws IOException {
        String requestUri = request.getRequestURI();

        // 跳转
        if (StringUtil.equals(request.getContextPath() + Constant.URL_ROOT, requestUri)) {
            response.sendRedirect(requestUri + "/");
            return true;
        }

        // vue index
        if (StringUtil.equals(request.getContextPath() + Constant.URL_ROOT + "/", requestURI)) {
            BudoGraphViewUtil.writeIndexResponse_VUE(applicationContext, request, response);
            return true;
        }

        // freemarker index
        if (StringUtil.equals(request.getContextPath() + Constant.URL_ROOT + "/index", requestURI)) {
            BudoGraphViewUtil.writeIndexResponse_FM(applicationContext, request, response);
            return true;
        }

        if (StringUtil.endsWith(requestURI, ".html")) {
            BudoGraphViewUtil.writeStaticResponse(applicationContext, request, response);
            return true;
        }

        if (StringUtil.endWith(requestURI, "line-graph")) {
            BudoGraphViewUtil.writeStaticResponse_2(applicationContext, request, response, "META-INF/resources/budo-graph/line-graph.htm");
            return true;
        }

        if (StringUtil.endWith(requestURI, "force-graph")) {
            BudoGraphViewUtil.writeStaticResponse_2(applicationContext, request, response, "META-INF/resources/budo-graph/force-graph.htm");
            return true;
        }

        if (StringUtil.endWith(requestURI, "application.json")) {
            BudoGraphViewUtil.writeApplication(applicationContext, response);
            return true;
        }

        if (StringUtil.endWith(requestURI, "application-force.json")) {
            Collection<Map<String, Object>> applicationForce = ApplicationForceUtil.applicationForce(applicationContext);
            ResponseUtil.writeToResponse(response, JSONUtils.toJSONString(applicationForce));
            return true;
        }

        if (StringUtil.endsWith(requestURI, ".json")) {
            BudoGraphViewUtil.writeApiResponse(request, response, applicationContext);
            return true;
        }

        // 非 json 结尾的api
        boolean isHtmlApi = BudoGraphViewUtil.isHtmlApi(requestURI);
        if (isHtmlApi) {
            response.setContentType(Constant.ContentType.TEXT_HTML);
            BudoGraphViewUtil.writeApiResponse(request, response, applicationContext);
            return true;
        }

        log.warn("#163 doFilter else, requestURI=" + requestURI + ", request=" + request);
        return false;
    }

    private void writeSubmitLoginResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Boolean checkAuthorize_2 = GraphAuthorizeUtil.checkAuthorize_2(request, this);
        if (checkAuthorize_2) { // 登陆成功
            String usernameParam = request.getParameter(PARAM_NAME_USERNAME);

            HttpSession session = request.getSession();
            session.setAttribute(GraphAuthorizeUtil.SESSION_USER_KEY, usernameParam);

            response.getWriter().print("success");
            return;
        }

        response.getWriter().print("error");
    }
}